import { dateUtil } from './dateUtil'

/**
 * @description 实例化一个clsGanZhi对象, 根据天干和地支的索引
 * @param {int} theTianGan 天干索引 ( 0 ~ 9 )
 * @param {int} theDiZhi 地支索引 ( 0 ~ 11 )
 * @return {clsGanZhi}
 */
export class GanZhi {
	/**
	 * @description 本对象天干的索引0~9
	 * @type{int}
	 */
	TianGan : number;
	/**
	 * @description 本对象地支的索引0~11
	 * @type{int}
	 */
	DiZhi : number;
	constructor(theTianGan : number, theDiZhi : number) {
		this.TianGan = theTianGan;
		this.DiZhi = theDiZhi;
	};
	/**
	 * @description 获取本对象的干支文本
	 * @return {String}
	 */
	getText() : string {
		return GanZhi.TianGanLine.charAt(this.TianGan) + "" + GanZhi.DiZhiLine.charAt(this.DiZhi);
	};

	/**
	 * @description 获取本对象的天干文本
	 */
	getTianGanText() {
		return GanZhi.TianGanLine.charAt(this.TianGan);
	};

	/**
	 * @description 获取本对象的地支文本
	 */
	getDiZhiText() {
		return GanZhi.DiZhiLine.charAt(this.DiZhi);
	};

	getHuaJiaIndex() {
		return GanZhi.getHuaJiaByGanZhi(this);
	}
	/**
	 * @description 从干支对象计算花甲索引 ( 0 - 59 )
	 * @param {clsGanZhi} theGanZhi alt 干支对象
	 * @return {int}
	 */
	static getHuaJiaByGanZhi(theGanZhi : GanZhi) : number {
		return GanZhi.getHuaJiaByIndex(theGanZhi.TianGan, theGanZhi.DiZhi);
	};

	/**
	 * 从花甲索引 ( 0 - 59 ) 返回一个干支对象
	 */
	static getGanzhiByHuajia(huajiaIndex : number) : GanZhi {
		return new GanZhi(huajiaIndex % 10, huajiaIndex % 12);
	}

	/**
	 * 获取指定公历日期当天的干支对象, 如果时辰在23点之后应设置 after23=true
	 * @param after23 时辰是否在23点之后(此时是第2天的子时)
	 */
	static getGanzhiFromDate(date : Date, after23 ?: boolean) : GanZhi {
		let count = dateUtil.GetDaysFrom(dateUtil.DayGanZhiZero, date);
		// console.log("GanZhi->getGanzhiFromDate: " + (dateUtil.FormatDate(date, "yyyy-MM-dd") ?? "") + "距起算日 " + (count?.toString() ?? "") + "天");
		if (count < 0) {
			count = -count;
			count = count % 60;
			count = 60 - count;
		}
		let days = (count + (after23 ? 1 : 0)) % 60;
		return this.getGanzhiByHuajia(days);
	}

	/**
	 * @description 获取地支遁藏,没有参数表示从本对象中的地支计算,有一个参数表示从指定地支计算
	 * @param {int} theDiZhiIndex alt 指定的地支索引(0~11),不设置此参数表示从本对象的地支计算
	 * @return {intArray}
	 */
	getDiZhiIn(theDiZhiIndex ?: number) : number[] {
		if (!theDiZhiIndex || theDiZhiIndex < 0) {
			return this.getDiZhiIn(this.DiZhi);
		} else {
			switch (theDiZhiIndex) {
				case 0:
					return [9];
				case 1:
					return new Array(9, 7, 5);
				case 2:
					return new Array(0, 2, 4);
				case 3:
					return [1];
				case 4:
					return new Array(1, 4, 9);
				case 5:
					return new Array(6, 2, 4);
				case 6:
					return new Array(5, 3);
				case 7:
					return new Array(1, 5, 3);
				case 8:
					return new Array(4, 6, 8);
				case 9:
					return [7];
				case 10:
					return new Array(7, 3, 4);
				case 11:
					return new Array(8, 0);
				default:
					throw ("调用getDiZhiIn时出现错误的地支索引:" + arguments[0])
			}
		}
	}

	/**
	 * @description 获取五行索引,没有参数表示从本对象的天干计算,有一个参数表示从指定天干索引计算
	 * @return {int}
	 */
	getWuXingTG(tianGanIndex ?: number) : number {
		if (!tianGanIndex || tianGanIndex < 0) {
			return this.getWuXingTG(this.TianGan);
		} else {
			switch (tianGanIndex) {
				case 0:
				case 1:
					return 2;
				case 2:
				case 3:
					return 3;
				case 4:
				case 5:
					return 4;
				case 6:
				case 7:
					return 0;
				case 8:
				case 9:
					return 1;
				default:
					return -1;
			}
		}
	}

	/**
	 * @description 获取五行的文本,没有参数表示从本对象的天干计算,有一个参数表示从指定的天干索引计算
	 * @return {String}
	 */
	getWuXingTGText(tianGanIndex ?: number) : string {
		if (!tianGanIndex || tianGanIndex < 0) {
			return dateUtil.WuXingLine[this.getWuXingTG()];
		} else {
			return dateUtil.WuXingLine[this.getWuXingTG(arguments[0])];
		}
	}
	/**
	 * 创建年干支对象. 根据年份
	 */
	static createYearGanzhi(year : number) : GanZhi {
		return GanZhi.getGanzhiByHuajia(GanZhi.getHuaJiaIndexByYear(year));
	}
	/**
	 * @description 获取指定年的干支信息
	 * @param {int} year 指定的年份(1901~2100)
	 * @return {GanZhi}
	 */
	static getYearGanZhi(year : number) : GanZhi {
		// var dValue = (theYear - 4) % 60;
		// return new GanZhi(dValue % 10, dValue % 12);
		return GanZhi.createYearGanzhi(year);
	};

	/**
	 * 使用年天干索引和月地支索引生成月干支对象(年上起月)
	 */
	static createMonthGanzhi(yearTiangan : number, monthDizhi : number) : GanZhi {
		var mtg = ((yearTiangan % 5) + 1) * 2;
		return new GanZhi((mtg + monthDizhi) % 10, (monthDizhi + 2) % 12);
	}

	/**
	 * 使用日天干索引和时辰地支索引生成时辰干支对象(日上起时), 时辰为 0 ~ 11
	 */
	static createHourGanzhi(dayTiangan : number, hour12 : number) : GanZhi {
		var dtg = (dayTiangan % 5) * 2;
		return new GanZhi((dtg + hour12) % 10, hour12);
	}
	/**
	 * @description 根据指定的年份获取大命信息
	 * @param {int} theYear alt 指定的年份(1901~2100)
	 * @return {String}
	 */
	static getDaMingByYear(theYear : number) : string {
		return GanZhi.NaYinResource[Math.floor((theYear - 4) / 2) % 30];
	};
	/** 
	 * @description 根据指定的干支返回大命信息
	 * @param {GanZhi} theGanZhi alt 干支
	 * @return {String}
	 */
	static getDaMingByGanZhi(theGanZhi : GanZhi) : string {
		return GanZhi.NaYinResource[GanZhi.getHuaJiaByGanZhi(theGanZhi) >> 1];
	};
	/**
	 * @description 从花甲索引获取花甲文本
	 * @param {int} theHuaJia
	 */
	static getHuaJiaText(theHuaJia : number) : string {
		return GanZhi.NaYinResource[theHuaJia];
	};

	/**
	 * @description 从干支索引计算花甲索引
	 * @param {int} theTianGan alt 天干索引(0~9)
	 * @param {int} theDiZhi alt 地支索引(0~11)
	 * @return {int}
	 */
	static getHuaJiaByIndex(theTianGan : number, theDiZhi : number) : number {
		//'公式:(12-地支Index-天干Index) mod 12 ,再*5+天干数就是
		return ((12 - theDiZhi + theTianGan) % 12) * 5 + theTianGan;
		//'公式:(6 * 天干Index - 5 * 地支Index) mod 60  不同的计算公式,相同的结果
		// return ((60 + 6 * theTianGan - 5 * theDiZhi) % 60);
	};
	/**
	 * @description 花甲纳音数组(共30个)
	 * @type {String}
	 */
	static NaYinResource : string[] = [
		"海中金", "炉中火", "大林木", "路旁土", "剑锋金", "山头火",
		"洞下水", "城墙土", "白蜡金", "杨柳木", "泉中水", "屋上土",
		"霹雷火", "松柏木", "长流水", "沙中金", "山下火", "平地木",
		"壁上土", "金箔金", "佛灯火", "天河水", "大驿土", "钗钏金",
		"桑松木", "大溪水", "沙中土", "天上火", "石榴木", "大海水"
	]
	/**
	 * @description 从花甲索引获取纳音文本
	 * @param {int} theHuaJia 花甲索引 ( 0 ~ 59)
	 */
	static getNaYinText(theHuaJia : number) : string {
		return GanZhi.NaYinResource[theHuaJia >> 1];
	}

	/**
	 * @description 10个天干单字组成的字符串
	 */
	static TianGanLine = "甲乙丙丁戊己庚辛壬癸"
	static getTianGanText(index : number) { return GanZhi.TianGanLine.charAt(index); }
	/**
	 * @description 12个地支单字组成的字符串
	 */
	static DiZhiLine = "子丑寅卯辰巳午未申酉戌亥"
	static getDiZhiText(index : number) {
		return GanZhi.DiZhiLine.charAt(index);
	}
	/**
	 * @description 从天干和地支的索引返回一组干支文本
	 */
	static getGanZhiText(tianGan : number, diZhi : number) { return GanZhi.getTianGanText(tianGan) + GanZhi.getDiZhiText(diZhi) }

	/**
	 * @description 从花甲索引返回一组干支文本
	 */
	static getGanZhiTextByHuajia(huaJia : number) {
		let gan = huaJia % 10;
		let zhi = huaJia % 12;
		return GanZhi.getGanZhiText(gan, zhi);
	}

	/**
	 * @description 计算指定年份的花甲索引 ( 0 ~ 59)
	 * @param {int} theYear
	 * @return {int}
	 */
	static getHuaJiaIndexByYear(theYear : number) : number {
		return (theYear - 4) % 60;
	}

	/**
	 * 从花甲索引得到一个干支索引元组
	 */
	static getGanzhiTuple(huajiaIndex : number) : [number, number] {
		return [huajiaIndex % 10, huajiaIndex % 12];
	}
}